#include "widget.h"
#include "ui_widget.h"

#include <QSqlDatabase>
#include <QtDebug>
#include <QSqlError>
#include <QSqlRecord>
#include <QItemSelectionModel>
#include <QModelIndexList>
#include <QMessageBox>
#include <QSqlRelation>
#include <QSqlRelationalDelegate>
#include <QSqlQuery>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("127.0.0.1");
    db.setPort(3306);
    db.setUserName("root");
    db.setPassword("root");
    db.setDatabaseName("study");

    if(!db.open())
    {
        qDebug() << "连接失败" << db.lastError().text();
    }

    // 查询
    this->stuModel = new QSqlRelationalTableModel(this);
    // 让 stuModel 与 student 数据表进行绑定
    this->stuModel->setTable("student");

    // 查询之前设置关联关系
    // 参数1：使用当前表的哪个字段关联其他表
    // 参数2：关联表信息设置 QSqlRelation 对象
    //       参数1：关联的表名
    //       参数2：关联表的哪一个字段
    //       参数3：使用关联表中的哪个字段来代替现有的字段
    this->stuModel->setRelation(6, QSqlRelation("dept", "dno", "dname"));

    // 绑定完成之后，就能使用 select() 方法查询student表中的数据，查询完成之后，模型中就有student表中的数据了
    this->stuModel->select();
    // 将模型中的数据显示在 tableView 中
    ui->tableView->setModel(this->stuModel);

    ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));

    // 必须查询执行完成之后才能修改模型的头部
    this->stuModel->setHeaderData(0, Qt::Horizontal, "学号");
    this->stuModel->setHeaderData(1, Qt::Horizontal, "姓名");
    this->stuModel->setHeaderData(2, Qt::Horizontal, "昵称");
    this->stuModel->setHeaderData(3, Qt::Horizontal, "性别");
    this->stuModel->setHeaderData(4, Qt::Horizontal, "年龄");
    this->stuModel->setHeaderData(5, Qt::Horizontal, "入学时间");
    this->stuModel->setHeaderData(6, Qt::Horizontal, "所属学院");

    // 重设表格宽度
    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);

    // 隔行变色
    ui->tableView->setAlternatingRowColors(true);

    // 修改更新数据库的条件
    this->stuModel->setEditStrategy(QSqlTableModel::OnManualSubmit);

    // 添加
    // 1) 点击添加按钮时，增加一个空行（让用户输入新的数据）
    connect(ui->addBtn, &QPushButton::clicked, [this](){
        // ① 创建一个新的空记录
        QSqlRecord record = this->stuModel->record();

        // ② 获取模型的总行数
        int row = this->stuModel->rowCount();

        // ③ 将新的空记录添加到模型的最后一行
        this->stuModel->insertRecord(row, record);
    });

    // 2) 点击提交按钮时，将数据更新到数据库中
    connect(ui->submitBtn, &QPushButton::clicked, [this](){
        // 提交所有的变化到数据表中
        this->stuModel->submitAll();
    });

    // 删除
    connect(ui->delBtn, &QPushButton::clicked, [this](){
        // ① 获取所有选中的行（要被删除的数据）
        QItemSelectionModel* selectedModel = ui->tableView->selectionModel();

        // ② 从获取的行模型中获取行号信息
        QModelIndexList indexList = selectedModel->selectedRows();

        // 如果未选中行，删除按钮不生效
        if(indexList.size() == 0)
        {
            return;
        }

        // 弹出提示框
        QMessageBox warnBox(
                    QMessageBox::Warning,
                    "警告",
                    QString("确定删除%1条记录吗?").arg(indexList.size()),
                    QMessageBox::Yes | QMessageBox::No);
        warnBox.setButtonText(QMessageBox::Yes, QString("删除%1条记录").arg(indexList.size()));
        warnBox.button(QMessageBox::No)->setText("取消");

        int result = warnBox.exec();
        if(result == QMessageBox::Yes)
        {
            // ③ 遍历链表，得到每一行的行号
            for(int i = 0; i < indexList.size(); i++)
            {
                int index = indexList[i].row();
                this->stuModel->removeRow(index);
            }
        }
    });

    // 撤销
    connect(ui->revortBtn, &QPushButton::clicked, [this](){
        // 撤销所有的操作
        this->stuModel->revertAll();
        this->stuModel->submitAll();
    });

    // 升序排列
    connect(ui->ascBtn, &QPushButton::clicked, [this]() {
        // 获取当前选中的列
        QModelIndexList selectedColumns = ui->tableView->selectionModel()->selectedColumns();

        if (!selectedColumns.isEmpty())
        {
            // 只获取第一个选中的列进行排序
            int selectedColumn = selectedColumns.first().column();

            // 根据选中的列进行降序排序
            ui->tableView->sortByColumn(selectedColumn, Qt::AscendingOrder);
//            this->stuModel->sort(0, Qt::AscendingOrder);
        }
        else
        {
            // 未选中默认按第一列排序
            ui->tableView->sortByColumn(0, Qt::AscendingOrder);
        }
    });

    // 降序排列
    connect(ui->descBtn, &QPushButton::clicked, [this]() {
        // 获取当前选中的列
        QModelIndexList selectedColumns = ui->tableView->selectionModel()->selectedColumns();

        if (!selectedColumns.isEmpty())
        {
            // 只获取第一个选中的列进行排序
            int selectedColumn = selectedColumns.first().column();

            // 根据选中的列进行降序排序
            ui->tableView->sortByColumn(selectedColumn, Qt::DescendingOrder);
//            this->stuModel->sort(0, Qt::DescendingOrder);
        }
        else
        {
            // 未选中默认按第一列排序
            ui->tableView->sortByColumn(0, Qt::DescendingOrder);
        }
    });

    // 搜索
    connect(ui->searchBtn, &QPushButton::clicked, [this](){
        // ① 获取用户输入的关键字，并拼接成where子句中的模糊查询条件
        QString keyword = ui->lineEdit->text();

        // qDebug() << this->searchCondition << keyword << this->startDate.toString("yyyy-MM-dd") << this->endDate.toString("yyyy-MM-dd");
        QString filterStr = QString("%1 like '%%2%' and stime BETWEEN '%3' and '%4'")
                .arg(this->searchCondition).arg(keyword).arg(this->startDate.toString("yyyy-MM-dd"))
                .arg(this->endDate.toString("yyyy-MM-dd"));

        // ② 将模糊查询条件设置给 setFilter 方法
        this->stuModel->setFilter(filterStr);

        // ③ 重新调用 select 方法进行查询，查询结果会保存在模型中，视图也会跟着更新
        this->stuModel->select();
    });

    this->setTimeEditDefaultDate();
    ui->startDateEdit->setMaximumDate(this->endDate);  // 设置起始时间的最大范围
    ui->endDateEdit->setMinimumDate(this->startDate);  // 设置结束时间的最小范围
}


// 设置时间编辑器的默认时间
void Widget::setTimeEditDefaultDate()
{
    QSqlQuery query;
    QString sql = "SELECT MAX(stime), MIN(stime) FROM student";
    if (query.exec(sql))
    {
        if (query.next())
        {
            QDate maxDate = query.value(0).toDateTime().date();
            this->endDate = maxDate.addDays(1); // 设置为最大时间的后一天
            ui->endDateEdit->setDate(this->endDate);
            QDate minDate = query.value(1).toDateTime().date();
            this->startDate = minDate.addDays(-1); // 设置为最小时间的前一天
            ui->startDateEdit->setDate(this->startDate);
        }
    }
}

Widget::~Widget()
{
    delete ui;
}

// 根据选择设置筛选条件
void Widget::on_searchConditionBox_activated(int index)
{
    QString keyword = ui->lineEdit->text();
    if(index == 0)
    {
        this->searchCondition = "snickname";
    }
    else if(index == 1)
    {
        this->searchCondition = "sname";
    }
}

void Widget::on_startDateEdit_dateChanged(const QDate &date)
{
    this->startDate = date;
}

void Widget::on_endDateEdit_dateChanged(const QDate &date)
{
    this->endDate = date;
}

void Widget::on_sortConditionBox_activated(int index)
{
    ui->ascBtn->setChecked(false);
    ui->descBtn->setChecked(false);
    if(index == 0)
    {
        this->sortCondition = 0;
    }
    else if (index == 1)
    {
        this->sortCondition = 5;
    }
    else if (index == 2)
    {
        this->sortCondition = 1;
    }
}


void Widget::on_ascRadioBtn_clicked()
{
    ui->tableView->sortByColumn(this->sortCondition, Qt::AscendingOrder);
}

void Widget::on_descRadioBtn_clicked()
{
    ui->tableView->sortByColumn(this->sortCondition, Qt::DescendingOrder);
}
